package com.piggy.auth.services;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.piggy.auth.bo.OAuthReqPhone;
import com.piggy.auth.bo.OAuthReqPwd;
import com.piggy.auth.bo.OAuthRes;
import com.piggy.auth.bo.OAuthResetPwd;
import com.piggy.common.core.constant.BizConstants;
import com.piggy.common.core.constant.SecurityConstants;
import com.piggy.common.core.constant.TokenConstants;
import com.piggy.common.core.domain.R;
import com.piggy.common.core.enums.CacheKeyEnums;
import com.piggy.common.core.exception.base.BaseException;
import com.piggy.common.core.utils.FeignResultUtils;
import com.piggy.common.core.utils.RegexUtils;
import com.piggy.common.redis.cache.CacheUtils;
import com.piggy.common.satoken.constants.SaTokenConst;
import com.piggy.common.satoken.enums.DeviceType;
import com.piggy.common.satoken.helper.LoginHelper;
import com.piggy.common.satoken.utils.SecurityUtils;
import com.piggy.logi.sys.api.RemoteLogiUserService;
import com.piggy.logi.sys.api.domain.LogiSysUser;
import com.piggy.sys.api.RemoteClientService;
import com.piggy.sys.api.RemoteSmsService;
import com.piggy.sys.api.domain.SysClientDetails;
import com.piggy.sys.api.model.LoginUser;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.logging.Log;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Slf4j
@Service
@RequiredArgsConstructor
public class LogiSysLoginService {

    @Resource
    private RemoteLogiUserService userService;

    @Resource
    private RemoteClientService clientService;

    @Resource
    private RemoteSmsService smsService;

    public OAuthRes login(OAuthReqPwd oauth) {

        R<SysClientDetails> clientDetailsR = clientService.getClientDetailsById(oauth.getClientId(), SecurityConstants.INNER);
        FeignResultUtils.throwIfFailed(clientDetailsR);
        SysClientDetails clientDetails = clientDetailsR.getData();

        if (!SecurityUtils.matchesPassword(oauth.getClientSecret(), clientDetails.getClientSecret())) {
            throw new BaseException("无效客户端");
        }

        R<LoginUser<LogiSysUser>> userR = null;
        if (RegexUtils.isMobile(oauth.getPhone())) {
            userR = userService.getUserByPhoneByDept(oauth.getPhone(), oauth.getDept(), SecurityConstants.INNER);
            FeignResultUtils.throwIfFailed(userR);
        } else if (RegexUtils.isEmail(oauth.getEmail())) {
            userR = userService.getUserByEmailByDept(oauth.getPhone(), oauth.getDept(), SecurityConstants.INNER);
            FeignResultUtils.throwIfFailed(userR);
        } else {
            userR = userService.getUserInfoByDept(oauth.getPhone(), oauth.getDept(), SecurityConstants.INNER);
            FeignResultUtils.throwIfFailed(userR);
        }

        LogiSysUser user = userR.getData().getSysUser();
        String password = user.getPassword();
        if (!SecurityUtils.matchesPassword(oauth.getPassword(), password)) {
            throw new BaseException("密码错误");
        }
        // 检查登录设备类型

        // 此处可根据登录用户的数据不同 自行创建 loginUser
        LoginUser<LogiSysUser> loginUser = userR.getData();
        loginUser.setClientDetails(clientDetails);
        loginUser.setUserName(loginUser.getSysUser().getUserName());
        loginUser.setPhone(loginUser.getSysUser().getPhonenumber());
        loginUser.setUserId(loginUser.getSysUser().getUserId());
        loginUser.setTClass(LogiSysUser.class);
        loginUser.setBiz(BizConstants.LOGI);
        // 生成token
        LoginHelper.loginByDevice(loginUser, user.getSessionTimeout() * 3600, DeviceType.getByCode(oauth.getDeviceType()));

        return new OAuthRes()
                .setTokenType(SaTokenConst.BEARER)
                .setAccessToken(StpUtil.getTokenValue())
                .setFirstLogin(ObjectUtil.isNull(user.getLoginDate()));

    }

    public R<LogiSysUser> register(OAuthReqPhone oauth) {
        if (StrUtil.isBlank(oauth.getPhone())) {
            throw new BaseException("手机号码不能为空!");
        }
        if (ObjectUtil.isEmpty(oauth.getCode())) {
            throw new BaseException("验证码不能为空!");
        }
        if (StrUtil.isAllBlank(oauth.getPassword(), oauth.getConfirePwd())) {
            throw new BaseException("密码不能为空!");
        }
        if (!CacheUtils.hasKey(CacheKeyEnums.RegUserSms.getKey(oauth.getPhone()))) {
            throw new BaseException("验证码已过期!");
        }
        if (!StrUtil.equals(oauth.getCode(), CacheUtils.getCache(CacheKeyEnums.RegUserSms.getKey(oauth.getPhone()), String.class))) {
            throw new BaseException("验证码不正确!");
        }
        R<LogiSysUser> sysUserR = userService.register(new LogiSysUser()
                .setPassword(oauth.getPassword())
                .setPhonenumber(oauth.getPhone()), SecurityConstants.INNER);
        FeignResultUtils.throwIfFailed(sysUserR);

        return sysUserR;
    }

    public boolean logout() {
        try {
            Long loginId = StpUtil.getLoginIdAsLong();
            if (ObjectUtil.isNotNull(loginId)) {
                StpUtil.kickout(loginId);
            }
            StpUtil.logout();
        } catch (NotLoginException e) {
            return true;
        } catch (Exception e) {
            log.error(e.getMessage());
            return true;
        }
        return true;
    }

    public Boolean kickout(OAuthReqPwd oauth) {

        Long loginId = StpUtil.getLoginIdAsLong();

        if (ObjectUtil.isNotNull(loginId) && StrUtil.isNotBlank(oauth.getDeviceType())) {
            StpUtil.kickout(loginId, oauth.getDeviceType());
            return true;
        }

        if (ObjectUtil.isNotNull(loginId)) {
            StpUtil.kickout(loginId);
            return true;
        }

        StpUtil.kickoutByTokenValue(StpUtil.getTokenValue());
        return true;

    }

    public Boolean resetMainUserPwd(OAuthResetPwd oauth) {
        if (StrUtil.isBlank(oauth.getPhone())) {
            throw new BaseException("手机号码不能为空!");
        }
        if (ObjectUtil.isEmpty(oauth.getCode())) {
            throw new BaseException("验证码不能为空!");
        }
        if (!CacheUtils.hasKey(CacheKeyEnums.RegUserSms.getKey(oauth.getPhone()))) {
            throw new BaseException("验证码已过期!");
        }
        if (!StrUtil.equals(oauth.getCode(), CacheUtils.getCache(CacheKeyEnums.RegUserSms.getKey(oauth.getPhone()), String.class))) {
            throw new BaseException("验证码不正确!");
        }
        R<Integer> ret = userService.resetMainUserPwd(oauth.getPhone(), oauth.getPassword(), SecurityConstants.INNER);
        FeignResultUtils.throwIfFailed(ret);
        return true;
    }


    public R<LogiSysUser> getMainUser(String phone) {
        if (StrUtil.isBlank(phone)) {
            throw new BaseException("手机号码不能为空!");
        }
        R<LogiSysUser> ret = userService.getMainUser(phone, SecurityConstants.INNER);
        FeignResultUtils.throwIfFailed(ret);
        return ret;
    }

    public R<Boolean> verify(String phone, String verifyCode) {
        if (StrUtil.isBlank(phone)) {
            throw new BaseException("手机号码不能为空!");
        }
        if (ObjectUtil.isEmpty(verifyCode)) {
            throw new BaseException("验证码不能为空!");
        }
        if (!CacheUtils.hasKey(CacheKeyEnums.RegUserSms.getKey(phone))) {
            throw new BaseException("验证码已过期!");
        }
        if (!StrUtil.equals(verifyCode, CacheUtils.getCache(CacheKeyEnums.RegUserSms.getKey(phone), String.class))) {
            throw new BaseException("验证码不正确!");
        }
        return R.ok(true);
    }
}
